#include "ad.h"

uint16_t ad_value[ADC_CHANNEL_NUM];

static void AD_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(ADC_GPIO_CLK, ENABLE);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; // 设置为模拟输入
    GPIO_InitStructure.GPIO_Pin = ADC_GPIO_PINS;
    GPIO_Init(ADC_CPIO_PROT, &GPIO_InitStructure);
}

static void AD_DMA_Config(void)
{
    DMA_InitTypeDef DMA_InitStructure;

    RCC_AHBPeriphClockCmd(DMA_CLK, ENABLE); // 使能 DMA 时钟

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->DR;             // 设置外设基地址为ADC的DR寄存器的地址
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; // 外设数据宽度为半字
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;            // 失能外设地址自增
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ad_value;                  // 设置存储器基地址为ad_value的首地址
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;         // 存储器数据宽度为半字
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;                     // 使能存储器地址自增
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;                          // 设置数据传输方向为外设到存储器
    DMA_InitStructure.DMA_BufferSize = DMA_BUFFERSIZE;                          // 设置传输数据数目
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;                               // 设置为单次模式
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;                                // 失能存储器到存储器模式
    DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;                       // 设置优先级为中等
    DMA_Init(DMA_CHANNEL, &DMA_InitStructure);                                  // 初始化 DMA 的通道
}

static void AD_Config(void)
{
    ADC_InitTypeDef ADC_InitStructure;

    RCC_APB2PeriphClockCmd(ADC_CLK, ENABLE);             // 使能ADC时钟
    RCC_ADCCLKConfig(RCC_PCLK2_Div6);                    // 配置ADC时钟为PCLK2的六分频（72M/6 = 12MHz）

    ADC_RegularChannelConfig(ADC, ADC_CHANNEL0, 1, ADC_SampleTime_55Cycles5); // 配置ADC的规则通道0，序列1，采样时间为55.5个周期
    ADC_RegularChannelConfig(ADC, ADC_CHANNEL1, 2, ADC_SampleTime_55Cycles5); // 配置ADC的规则通道1，序列2，采样时间为55.5个周期

    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;                  // 设置ADC工作在独立模式
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;              // 数据右对齐
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 禁用外部触发转换
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;                 // 使用单次转换模式
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;                        // 使能扫描转换模式
    ADC_InitStructure.ADC_NbrOfChannel = ADC_CHANNEL_NUM;               // 设置转换通道数量
    ADC_Init(ADC, &ADC_InitStructure);

    ADC_DMACmd(ADC, ENABLE); // 使能ADC的DMA触发信号
    
    ADC_Cmd(ADC, ENABLE); // 使能ADC

    ADC_ResetCalibration(ADC);                                     // 复位ADC的校准寄存器
    while (ADC_GetResetCalibrationStatus(ADC) == SET);             // 等待复位校准结束
    ADC_StartCalibration(ADC);                                     // 启动ADC的校准
    while (ADC_GetCalibrationStatus(ADC) == SET);                  // 等待校准完成
}

void AD_Init(void)
{
    AD_GPIO_Config();
    AD_DMA_Config();
    AD_Config();
}

void AD_GetValue(void)
{
    DMA_Cmd(DMA_CHANNEL, ENABLE);                           // 使能 DMA 的通道
    ADC_SoftwareStartConvCmd(ADC, ENABLE);                  // 启动ADC的软件转换
    while (DMA_GetFlagStatus(DMA_FLAG_TC) == RESET);        // 等待传输完成标志位置位
    DMA_ClearFlag(DMA_FLAG_TC);                             // 清除传输完成标志位

    DMA_Cmd(DMA_CHANNEL, DISABLE);                          // 失能 DMA 的通道
    DMA_SetCurrDataCounter(DMA_CHANNEL, DMA_BUFFERSIZE);    // 设置当前数据传输数目
}
